package com.wanxi.step07test.service.impl;

import com.wanxi.step07test.dto.ResultDTO;
import com.wanxi.step07test.model.LoginParams;
import com.wanxi.step07test.model.Permission;
import com.wanxi.step07test.model.SUser;
import com.wanxi.step07test.mapper.RoleMapper;
import com.wanxi.step07test.mapper.SUserMapper;
import com.wanxi.step07test.service.SUserService;
import com.wanxi.step07test.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class SUserServiceImpl implements SUserService {
    @Autowired
    private SUserMapper sUserMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Value("${jwt.tokenHead}")
    String tokenHead;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.expiration}")
    private Long expiration;



//    @Autowired
//    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;


    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();


    @Override
    public SUser getSUserByName(String name) {
        List<SUser> users = sUserMapper.getSUserByName(name);
//        Assert.isTrue(users.size() != 1,"您输入的账户不存在，或者有多个相同的账户");
        return users.get(0);
    }

    @Override
    public List<Permission> getPermissionsBySUserId(Integer sUserId) {
        return sUserMapper.getPermissionBySUserId(sUserId);
    }

    @Override
    public ResultDTO login(LoginParams loginParams) {
        String code = loginParams.getCode();
        String vCode = (String) redisTemplate.opsForValue().get(loginParams.getUuid());

        if (vCode == null || !code.equals(vCode)){
          return ResultDTO.builder()
                    .code(0)
                    .msg("error-code")
                    .build();
        }

        //从redis查，没有就从数据库里查
        SUser sUser = findSUserFromRedis(loginParams.getUsername());
        if(sUser==null){
            return ResultDTO.builder()
                    .code(0)
                    .msg("error")
                    .build();
        }

        //验证密码
        String password = loginParams.getPassword();
        boolean matches = passwordEncoder.matches(password, sUser.getPassword());
        if (!matches){
            return ResultDTO.builder()
                    .code(0)
                    .msg("error")
                    .build();
        }

        //登录成功后缓存用户信息12小时，token为token失效时间的双倍
        String userKey = "user:" + sUser.getUsername();
        redisTemplate.opsForValue().set(userKey,sUser,12,TimeUnit.HOURS);

        HashMap<String, String> data = new HashMap<>();

        String token = jwtTokenUtil.generateToken(sUser);
        String tokenKey = "token:" + token;
        redisTemplate.opsForValue().set(tokenKey,token,expiration*2, TimeUnit.MILLISECONDS);

        data.put("tokenHead",tokenHead);
        data.put("access_token",token);
        // localStorage.setItem("Authorization","Bearer sdsdfdfds")
        // $ajax{data:{},type:"",header:{"Authorization":"Bearer sdsdfdfds"}}
        return ResultDTO.builder()
                .code(0)
                .msg("success")
                .data(data)
                .build();

    }


    private SUser findSUserFromRedis(String username){
        String userKey = "user:" + username;
        SUser sUserFromRedis = (SUser) redisTemplate.opsForValue().get(userKey);
        if(sUserFromRedis==null){
            SUser sUser = sUserMapper.findByName(username);
            redisTemplate.opsForValue().set(userKey,sUser,12,TimeUnit.HOURS);
            return sUser;
        }
        return sUserFromRedis;
    }


//    @Override
//    public String login(LoginParams loginParams) {
//        String username = loginParams.getUsername();
//        Assert.notNull(username,"账号必须不能为空");
//        String password = loginParams.getPassword();
//        Assert.notNull(password,"密码必须不能为空");
//        SUser sUser = getSUserByName(username);
//        boolean matches = passwordEncoder.matches(password, sUser.getPassword());
//        if(matches){
//
//            //登录成功后缓存用户信息12小时，token为token失效时间的双倍
//            String userKey = "user:" + sUser.getUsername();
//            redisTemplate.opsForValue().set(userKey,sUser,12,TimeUnit.HOURS);
//
//            String token = jwtTokenUtil.generateToken(sUser);
//            String tokenKey = "token:" + token;
//            redisTemplate.opsForValue().set(tokenKey,token,expiration*2, TimeUnit.MILLISECONDS);
//
//            return token;
//        }
//        return null;
//    }

    @Override
    public ResultDTO add(SUser sUser) {
        SUser userExist = sUserMapper.findByName(sUser.getUsername());
        if (userExist != null){
            return ResultDTO.builder()
                    .code(0)
                    .msg("have same name")
                    .count(-1)
                    .data("")
                    .build();
        }else {
            String anWen = passwordEncoder.encode(sUser.getPassword());
            sUser.setPassword(anWen);

            int addUserCount = sUserMapper.add(sUser);

            String[] roleNames = sUser.getRole().split(",");

            Integer[] roleIds = roleMapper.findIdByName(roleNames);
//        Integer[] roleIds = Stream.of(role).map(Integer::valueOf).toArray(Integer[]::new);

            SUser user = sUserMapper.findByName(sUser.getUsername());
//        WxUser byId = wxUserMapper.findById(byName.getId());

            Integer userId = user.getId();
            int addRoleCount = sUserMapper.saveSUserAndRole(userId, roleIds);

            return ResultDTO.builder()
                    .code(0)
                    .msg("")
                    .count(addRoleCount)
                    .data(0)
                    .build();
        }




    }

    @Override
    public ResultDTO findAll(SUser sUser) {

        sUser.setPage((sUser.getPage() - 1) * sUser.getLimit());

        Integer count = sUserMapper.count(sUser);
        List<SUser> sUserList = sUserMapper.findAll(sUser);

        return ResultDTO.builder()
                .code(0)
                .msg("")
                .count(count)
                .data(sUserList)
                .build();
    }

    @Override
    public ResultDTO delete(SUser sUser) {


        int deleteUserCount = sUserMapper.delete(sUser);

        int deleteRoleCount = sUserMapper.deleteSUserAndRole(sUser);


        return ResultDTO.builder()
                .code(0)
                .msg("")
                .count(deleteRoleCount)
                .data("")
                .build();
    }

    @Override
    public ResultDTO findById(Integer id) {
   return ResultDTO.builder()
                .code(0)
                .msg("")
                .count(0)
                .data(sUserMapper.findById(id))
                .build();
    }

    @Override
    public ResultDTO update(SUser sUser) {
        SUser userExist = sUserMapper.findByName(sUser.getUsername());
        if (userExist == null){
            return ResultDTO.builder()
                    .code(0)
                    .msg("have no")
                    .count(-1)
                    .data("")
                    .build();
        }else {


            int addUserCount = sUserMapper.update(sUser);

            String[] roleNames = sUser.getRole().split(",");

            Integer[] roleIds = roleMapper.findIdByName(roleNames);

            Integer userId = sUser.getId();

            int delete = sUserMapper.deleteSUserAndRole(sUser);
            int updateRoleCount = sUserMapper.saveSUserAndRole(userId, roleIds);

            return ResultDTO.builder()
                    .code(0)
                    .msg("")
                    .count(updateRoleCount)
                    .data(0)
                    .build();
        }}

    @Override
    public ResultDTO updatePassword(SUser sUser) {
        SUser userExist = sUserMapper.findByName(sUser.getUsername());
        if (userExist == null){
            return ResultDTO.builder()
                    .code(0)
                    .msg("have no")
                    .count(-1)
                    .data("")
                    .build();
        }else {
            String anWen = passwordEncoder.encode(sUser.getPassword());
            sUser.setPassword(anWen);
            int updatePasswordCount = sUserMapper.updatePassword(sUser);
            return ResultDTO.builder()
                    .code(0)
                    .msg("")
                    .count(updatePasswordCount)
                    .data(0)
                    .build();
        }}

}






//    @RequestMapping(value = "/login", method = RequestMethod.POST)
//    public String login(String username, String password) {
//
//        //1. 根据用户名和密码验证该用户是否是合法用户
//
//        WxUser wxUser = (WxUser) userDetailsService.loadUserByUsername(username);
//        // 把输入的密码加密后进行比对
//        if (!this.passwordEncoder.matches(password, wxUser.getPassword())) {
//            // 抛出错误或其他
//
//        } else {
//            //
//
//            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
//                    = new UsernamePasswordAuthenticationToken(wxUser,null,wxUser.getAuthorities());
//            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
//        }
//        return "登录";
//        // 2. 验证通过后，创建一个UsernameAndPasswordAuthenticationToken对象
//
//        // 3. 把这个对系那个交给框架
//    }
//}
